<?php
class MemcacheFactory
{
	const TIMEOUT        = 1;
	const RETRY_INTERVAL = 15;

	private static $connectors = array();
	//private static $settings   = array();

    public static function create($dsn = null)
    {
		$dsn = trim($dsn);
        if(!$dsn) 
		{
			throw new NICED_ValidationException("no dsn passed in");
		}

        $dsn        = strtolower($dsn);
		$connectors = &self::$connectors;
        
        if(!isset($connectors[$dsn]) || !is_object($connectors[$dsn]))
        {
			self::getCacher($dsn);
        }
		
        return $connectors[$dsn];
    }

	private static function getCacher($dsn)
	{
		//$options    = &self::$settings[$dsn];
		$options = NICED_DBFactory::getDsnSetting($dsn);
		$connectors = &self::$connectors;
		
		//@see application/config/dsn.php
		if ('memcache' != strtolower($options['type']))
		{
			throw new NICED_ValidationException("dsn type in config is not memcache");
		}

		if(!($options['hosts'])) 
		{
			throw new NICED_ValidationException("dsn hosts in config not exists");
		}
		
		if (!class_exists('NICED_Memcache'))
		{
			throw new NICED_NotExistsException('NICED_Memcache class not exists');
		}

		$m = new NICED_Memcache();

		foreach($options['hosts'] as $n)
		{
			@list($host, $port, $weight) = explode(':', $n, 3);
			$weight = (isset($weight) && (int)$weight > 0) ? (int)$weight : 1;

			$m->addServer($host, $port, true, $weight, self::TIMEOUT, self::RETRY_INTERVAL, true, array(__CLASS__, 'failureCallback'));
		}

        if ($developer = SC::get("board_config.developer"))
        {
            $m = new NICED_NamespacedMemcache($m, $developer);
            NICED_LOG(SC::get("board_config.niced_log_level"), "create developer namespace ms");
        }

		$connectors[$dsn] = $m;	

		return $m;
	}
    
	public static function failureCallback($host, $port)
	{
        $e = new Exception();
        $e = $e->__toString();

        //error_log("NICED add memcache server fail: ".substr($e, strpos($e, 'Stack trace') + 11));
        NICED_LOG(ERROR, "[NICED] add memcache server fail: ".substr($e, strpos($e, 'Stack trace') + 11));

        //alarm
        NICED_ALARM("memcache_add_server_fail");

}

//public static function setSettings($settings)
//{
	//	self::$settings = $settings;
	//}

	//public static function getSettingByDsn($dsn)
	//{
	//	if (!$dsn)
	//	{
	//		throw new NICED_ValidationException('no dsn passed in');
	//	}

	//	$dsn = strtolower($dsn);

	//	return self::$settings[$dsn];
	//}

	public static function closeAll() 
	{
		$connectors = &self::$connectors;

        if(!($connectors)) 
		{
			return true;	
		}
		
        foreach(array_keys($connectors) as $key)
        {
            $c = $connectors[$key];
            if(is_object($c) && method_exists($c, 'close')) $c->close();
            unset($c);
        }
	}
} //end class
register_shutdown_function(array('MemcacheFactory', 'closeAll'));
